﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Properties;

namespace System
{
    /// <summary>
    /// 包含了与时间间隔相关的一些常用扩展方法
    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static class TimeSpanExtensions
    {
        #region string 字符串

        #region 时间间隔变成缩写格式

        /// <summary>
        /// 时间间隔变成缩写格式
        /// </summary>
        /// <param name="span"></param>
        /// <returns></returns>
        public static string ToShortDuration(this TimeSpan span)
        {
            string formatted = string.Format("{0}{1}{2}",
                                             span.Days > 0 ? string.Format("{0:0}{1} ", span.Days, ExtensionResources.Day.ToLower()[0]) : string.Empty,
                                             span.Hours > 0 ? string.Format("{0:0}{1} ", span.Hours, ExtensionResources.Hour.ToLower()[0]) : string.Empty,
                                             span.Minutes > 0 ? string.Format("{0:0}{1} ", span.Minutes, ExtensionResources.Minute.ToLower()[0]) : string.Empty);
            return formatted.Trim();
        }

        #endregion 时间间隔变成缩写格式

        #region 时间间隔变成长格式

        /// <summary>
        /// 时间间隔变成长格式
        /// </summary>
        /// <param name="span"></param>
        /// <returns></returns>
        public static string ToLongDuration(this TimeSpan span)
        {
            string formatted = string.Format("{0}{1}{2}",
                                             span.Days > 0 ? string.Format("{0:0} {1} ", span.Days, PluralizeInt(ExtensionResources.Day, span.Days)) : string.Empty,
                                             span.Hours > 0 ? string.Format("{0:0} {1} ", span.Hours, PluralizeInt(ExtensionResources.Hour, span.Hours)) : string.Empty,
                                             span.Minutes > 0 ? string.Format("{0:0} {1} ", span.Minutes, PluralizeInt(ExtensionResources.Minute, span.Minutes)) : string.Empty);
            return formatted.Trim();
        }

        #endregion 时间间隔变成长格式

        #endregion string 字符串

        #region Method 方法

        /// <summary>
        ///  返回长格式字符串
        /// </summary>
        /// <param name="keyword"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string PluralizeInt(string keyword, int value)
        {
            var suffix = ExtensionResources.PluralCurrencySuffix ?? ".";
            if (value > 1) return keyword + suffix.Replace(".", "");
            return keyword;
        }

        /// <summary>
        /// 将TimeSpan偏移指定的小时
        /// </summary>
        /// <param name="timeSpan"></param>
        /// <param name="hours"></param>
        /// <returns></returns>
        public static TimeSpan AddHours(this TimeSpan timeSpan, int hours)
        {
            return timeSpan.Add(new TimeSpan(hours, 0, 0));
        }

        /// <summary>
        /// 将TimeSpan偏移指定的分钟
        /// </summary>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static TimeSpan AddMinutes(this TimeSpan timeSpan, int minutes)
        {
            return timeSpan.Add(new TimeSpan(0, minutes, 0));
        }

        /// <summary>
        /// 将TimeSpan偏移指定的秒数
        /// </summary>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static TimeSpan AddSeconds(this TimeSpan timeSpan, int seconds)
        {
            return timeSpan.Add(new TimeSpan(0, 0, seconds));
        }

        /// <summary>
        /// 将TimeSpan偏移指定的天
        /// </summary>
        /// <param name="timeSpan"></param>
        /// <returns></returns>
        public static TimeSpan AddDays(this TimeSpan timeSpan, int days)
        {
            return timeSpan.Add(new TimeSpan(days, 0, 0, 0));
        }

        /// <summary>
        /// 转换Timespan为友好的显示方式
        /// </summary>
        /// <param name="ts"></param>
        /// <returns></returns>
        public static string ToFriendlyDisplay(this TimeSpan ts)
        {
            //天/时/分/秒/毫秒
            var arr = new string[] { "", "", "", "", "" };
            if (ts.Days > 0)
                arr[0] = string.Format("{0}天", ts.Days);
            if (ts.Hours > 0)
                arr[1] = string.Format("{0}时", ts.Hours);
            if (ts.Minutes > 0)
                arr[2] = string.Format("{0}分", ts.Minutes);
            if (ts.Seconds > 0)
                arr[3] = string.Format("{0}秒", ts.Seconds);
            if (ts.Milliseconds > 0)
                arr[4] = string.Format("{0}毫秒", ts.Milliseconds);

            return arr.JoinAsString("");
        }

        /// <summary>
        /// 计算指定的 <see cref="TimeSpan"/> 序列的和
        /// </summary>
        /// <param name="timespans"><see cref="TimeSpan"/> 序列</param>
        /// <returns></returns>
        public static TimeSpan Sum(this IEnumerable<TimeSpan> timespans)
        {
            return timespans.Aggregate(TimeSpan.Zero, (x, y) => x + y);
        }

        /// <summary>
        /// 计算指定的 <see cref="TimeSpan"/> 序列的和
        /// </summary>
        /// <param name="timespans"><see cref="TimeSpan"/> 序列</param>
        /// <returns></returns>
        public static TimeSpan? Sum(this IEnumerable<TimeSpan?> timespans)
        {
            return timespans.Aggregate((TimeSpan?)null, (x, y) =>
            {
                if (y.HasValue)
                    return x.HasValue ? x.Value + y.Value : y.Value;
                return x;
            });
        }

        /// <summary>
        ///     Multiply a <c>System.TimeSpan</c> by a <paramref name="factor"/>
        /// </summary>
        /// <param name="source">The given <c>System.TimeSpan</c> to be multiplied</param>
        /// <param name="factor">The multiplier factor</param>
        /// <returns>The multiplication of the <paramref name="source"/> by <paramref name="factor"/></returns>
        public static TimeSpan MultiplyBy(this TimeSpan source, int factor)
        {
            TimeSpan result = TimeSpan.FromTicks(source.Ticks * factor);
            return result;
        }

        /// <summary>
        ///     Multiply a <c>System.TimeSpan</c> by a <paramref name="factor"/>
        /// </summary>
        /// <param name="source">The given <c>System.TimeSpan</c> to be multiplied</param>
        /// <param name="factor">The multiplier factor</param>
        /// <returns>The multiplication of the <paramref name="source"/> by <paramref name="factor"/></returns>
        public static TimeSpan MultiplyBy(this TimeSpan source, double factor)
        {
            TimeSpan result = TimeSpan.FromTicks((long)(source.Ticks * factor));
            return result;
        }
        #endregion Method 方法
    }
}